-- 重写档案馆任务，能保留成功和失败的任务记忆
local thread = nil
local prefabs = {"archive_lockbox", "blank_certificate",}
local id_thread = "id_thread_dag"
local e_util = require "libs/entutil"
local p_util = require "libs/playerutil"
local t_util = require "libs/tableutil"
local loc_small,loc_base = "archive_orchestrina_small","archive_orchestrina_base"
local anim_all = {"one", "two", "three", "four", "five", "six", "seven"}

local function TIPS(color, content)
    TIP("档案馆任务", color, content, "head")
end
local function StopThread(message)
    GLOBAL.KillThreadsWithID(id_thread)
    if thread then
        TIPS("white", message or "任务结束")
    end
    thread = nil
end
local function marktarget(target, anim_target)
    if not target or not anim_target then return end
    if not target.false_check then
        target.false_check = {[anim_target] = true}
    elseif not target.false_check[anim_target] then
        target.false_check[anim_target] = true
    end
end

local function Fn()
    if thread then return StopThread("手动终止") end
    local base = e_util:FindEnt(nil, loc_base, nil, nil, {})
    if not base then return StopThread("档案馆不在周围") end

    local mode = "检查模式"
    local the_anim, the_target, last_pos, last_last_pos
    thread = GLOBAL.StartThread(function()
        while thread and base and base:IsValid() do
            if mode == "检查模式" then
                repeat GLOBAL.Sleep(GLOBAL.FRAMES*3) until not p_util:IsInBusy()
                if e_util:FindEnt(base, prefabs, 3) then
                    mode = "任务模式"
                else
                    local item = p_util:GetItemFromAll(prefabs)
                    if item then
                        local dist = e_util:GetDist(base)
                        if dist then
                            if dist < 3 then
                                p_util:DropItemFromInvTile(item)
                            else
                                p_util:Click(base)
                            end
                        else
                            break
                        end
                    else
                        break
                    end
                end
            elseif mode == "任务模式" then
                GLOBAL.Sleep(GLOBAL.FRAMES*3)
                -- 获取实时最大的动画标记作为【目标标记】
                local max_anim = 0
                local smalls = e_util:FindEnts(base, loc_small, 8, nil, {}, nil, nil, function(small)
                    local id = t_util:GetElement(anim_all, function(id, anim_str)
                        return e_util:IsAnim({anim_str, anim_str.."_pre"}, small) and id
                    end)
                    if id and id > max_anim then
                        max_anim = id
                    end
                    return true
                end)
                -- 读取有无【目标标记】的标签
                max_anim = max_anim + 1

                local target = t_util:GetElement(smalls, function(_, small)
                    local label_num = small._hx_label and GLOBAL.tonumber(small._hx_label:GetText())
                    if label_num == max_anim then
                        return small
                    end
                end)
                -- 没有标签则寻找最近的【目标标记】
                if not target then
                    local min_dist = 10000
                    t_util:IPairs(smalls, function(small)
                        -- 1、距离最近
                        -- 2、不能有标签（因为有标签的都走过了）
                        -- 3、不能有错误到达标记
                        local label_num = small._hx_label and GLOBAL.tonumber(small._hx_label:GetText())
                        if not label_num and not (small.false_check and small.false_check[max_anim]) then
                            local dist = e_util:GetDist(small)
                            if dist and dist < min_dist then
                                min_dist = dist
                                target = small
                            end
                        end
                    end)
                end

                if target then
                    if the_target ~= target then
                        marktarget(e_util:FindEnt(nil, loc_small, 4, nil, {}), the_anim)
                    end
                    the_target,the_anim = target, max_anim

                    local t_pos,c_pos,p_pos = target:GetPosition(), base:GetPosition(), GLOBAL.ThePlayer:GetPosition()
                    if last_last_pos == last_pos and last_pos == p_pos then
                        repeat
                            p_util:Click(base)
                            GLOBAL.Sleep(GLOBAL.FRAMES*3)
                        until not e_util:FindEnt(nil, loc_small, 2.5, nil, {})
                    else
                        p_util:Click(t_pos - (t_pos-c_pos) / t_pos:Dist(c_pos))
                    end
                    last_last_pos,last_pos = last_pos, p_pos

                    if max_anim == 8 then break end
                    local dist = e_util:GetDist(target)
                    if dist < 1.5 then
                        marktarget(target, max_anim)
                    end
                else
                    e_util:FindEnts(nil, loc_small, nil, nil, {}, nil, nil, function(small)
                        if small.false_check then
                            small.false_check[max_anim] = false
                        end 
                    end)
                end
            end
        end
        StopThread()
    end, id_thread)
end

---- 老三样姑且不管
InterruptedByMobile(function() return thread end, StopThread)
if GetModConfigData("sw_DAG") == "biubiu" then
    DEAR_BTNS:AddDearBtn(GLOBAL.GetInventoryItemAtlas("archive_lockbox.tex"), "archive_lockbox.tex", "档案任务改", "携带蒸馏的知识去科技馆吧！(也支持能力勋章)", false, Fn)
end
AddBindBtn("sw_DAG", Fn)